﻿#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//**************************十，操作符详解*************************************
/*******1. 移位操作符***********/

//int main()
//{
//	int a = 10;
//	//左移
//	a = a << 1;
//	printf("%d\n", a);
//
//	//右移
//	int b = 10;
//	b = b>> 1;
//	printf("%d\n", b);
//
//	int c = -10;
//	c = c >> 2;
//	printf("%d\n", c);
//	return 0;
//}

/***********2. 位操作符：&、|、^、~************/

//int main()
//{
//	int a = 3;
//	int b = -5;
//	//int c = a & b;//按位与
//	int c = a | b;//按位或
//
//	//00000000 00000000 00000000 00000011 3的原码
//	//00000000 00000000 00000000 00000011 3的反码
//	//00000000 00000000 00000000 00000011 3的补码
//
//	//10000000 00000000 00000000 00000101 5的原码
//	//11111111 11111111 11111111 11111010 5的反码
//	//11111111 11111111 11111111 11111011 5的补码
//
//	//00000000 00000000 00000000 00000011 3的补码
//	//11111111 11111111 11111111 11111011 5的补码
//	 
//	//00000000 00000000 00000000 00000011 与
//	// 
//	//11111111 11111111 11111111 11111011 或
//	//10000000 00000000 00000000 00000101 原码
//	printf("%d\n", c);
//	return 0;
//}

//int main()
//{
//	int a = 3;
//	int b = -5;
//	int c = a ^ b;//按位异或 相同为0，相异为1 
//
//	//00000000 00000000 00000000 00000011 3的原码
//	//00000000 00000000 00000000 00000011 3的反码
//	//00000000 00000000 00000000 00000011 3的补码
//
//	//10000000 00000000 00000000 00000101 5的原码
//	//11111111 11111111 11111111 11111010 5的反码
//	//11111111 11111111 11111111 11111011 5的补码
//
//	//00000000 00000000 00000000 00000011 3的补码
//	//11111111 11111111 11111111 11111011 5的补码
//	 
//	//11111111 11111111 11111111 11111000 补码
//	//10000000 00000000 00000000 00000111 反码
//	//10000000 00000000 00000000 00001000 原码 
//	printf("%d\n", c);
//	return 0;
//}

//int main()
//{
//	int a = 0;
//	a = ~a;
//	printf("%d\n",a);//按位取反，补码所有二进制位取反
//	//00000000 00000000 00000000 00000000补码
//	// 
//	//11111111 11111111 11111111 11111111补码
//	//10000000 00000000 00000000 00000000取反
//	//10000000 00000000 00000000 00000001原码
//	return 0;
//}


//练习：不能创建临时变量（第三个变量），实现两个整数的交换。
//int main()
//{
//	int a = 3;
//	int b = 5;
//
//	//(1)
//	/*int c = a;
//	a = b;
//	b = c;*/
//
//	//(2)
//	/*a = a + b;
//	b = a - b;
//	a = a - b;*/
//
//	//(3)			//异或是支持交换律的
//	/*a = a ^ b;       //a' = a ^ b
//	b = a ^ b;		   //b = a' ^ b = a ^ b ^ b --> b = a
//	a = a ^ b;*/	   //a =a ^ b ^ a --> a = b
//	printf("%d\n", a);
//	printf("%d\n", b);
//	return 0;
//}

//练习1：编写代码实现：求⼀个整数存储在内存中的⼆进制中1的个数

//(1)
//int main()
//{
//	int n = -1;
//	int count = 0;
//	while (n)
//	{
//		if (n % 2 == 1)
//		{
//			count++;
//		}
//		n /= 2;
//	}
//	printf("%d\n",count);
//
//	return 0;
//}

//(2)
//int main()
//{
//	int n = -1;
//	int count = 0;
//	int i = 0;
//	for (i = 0;i < 32;i++)
//	{
//		if ((n >> i) & 1 == 1)
//			count++;
//
//	}
//	printf("%d\n",count);
//	return 0;
//}

/*(3) n = n & (n - 1) 这个表达式会将n的二进制表示中最右边的1去掉*/
//int main()
//{
//	int n = 15;
//	int count = 0;
//	while (n)
//	{
//		count++;
//		n = n & (n - 1);
//	}
//	printf("%d\n",count);
//	return 0;
//}

//练习:判断n是否是2的幂次方数？
//int main()
//{
//	int n = 0;
//	scanf("%d",&n);
//	if (n & (n - 1) == 0)
//	{
//		printf("n是2的幂次方数");
//	}
//	else
//	{
//		printf("不是");
//	}
//	return 0;
//}

//练习2：⼆进制位置0或者置1
//编写代码将13⼆进制序列的第5位修改为1，然后再改回0

//int main()
//{
//	int n = 13;
//	n |= (1 << 4);
//	printf("%d\n", n);
//	n &= ~(1 << 4);
//	printf("%d",n);
//	return 0;
//}

/***********7. 逗号表达式************/
//逗号表达式，从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果
//int main()
//{
//	/*int a = 1;
//	int b = 2;
//	int c = (a > b, a = b + 10, a, b = a + 1);
//
//	printf("%d\n",c);*/
//
//
//	/*int a = 3, b = 5, c = 2, d = 10;
//	if (a = b + 1, c = a / 2, d > 0)*/
//
//
//	return 0;
//}

/******** 8. 结构成员访问操作符********/
//结构体，自定义类型

/*结构是⼀些值的集合，这些值称为成员变量。结构的每个成员可以是不同类型的变量，如：
标量、数组、指针，甚⾄是其他结构体。*/

//声明的一个结构体类型
//struct Stu
//{
//	char name[20];	//名字
//	int age;		//年龄
//	char sex[6];	//性别
//	char id[12];	//学号
//}s4;
//
//struct Stu s3;	  //s3也是一个结构体变量 - 全局的
//
//int main()
//{
//	struct Stu s1;//s1就是一个结构体变量 - 局部变量
//	struct Stu s2;//s2也是一个结构体变量
//	return 0;
//}
 
//struct Point
//{
//	int x;
//	int y;
//};
//
//struct Data
//{
//	int n;
//	double d;
//	struct Point p3;
//};
//
//struct Stu
//{
//	char name[20];	//名字
//	int age;		//年龄
//	char sex[6];	//性别
//	char id[12];	//学号
//};
//
//struct Point p1 = {10,20};

//结构体成员的直接访问
//结构体成员的直接访问是通过点操作符（.）访问的。点操作符接受两个操作数。
//int main()
//{
//	struct Data data = { 100, 205.5, {300,400} };
//	//struct Point p2;
//	struct Stu s1 = {0};
//	struct Stu s2 = {.age = 22,.id = "12345678",.sex = "男",.name = "李四"};
//
//	//printf("%s\n",s1.name);//结构体变量.结构体成员名
//	//s1.age = 18;
//	//printf("%d\n",s1.age);
//	//printf("%s\n",s1.sex);
//	//printf("%s\n",s1.id);
//
//	scanf("%s %d %s %s",s1.name,&s1.age,s1.sex,s1.id);
//
//	printf("%s\n", s1.name);
//	printf("%d\n", s1.age);
//	printf("%s\n", s1.sex);
//	printf("%s\n", s1.id);
//
//	return 0;
//
//}


/********9. 操作符的属性：优先级、结合性********/
//C语⾔的操作符有2个重要的属性：优先级、结合性，这两个属性决定了表达式求值的计算顺序。

/* * * * * 优先级 * * * * */
//优先级指的是，如果⼀个表达式包含多个运算符，哪个运算符应该优先执⾏。各种运算符的优先级是不⼀样的
  
/* * * * * 结合性 * * * * */
//如果两个运算符优先级相同，优先级没办法确定先计算哪个了，这时候就看结合性了，则根据运算符
//是左结合，还是右结合，决定执⾏顺序。⼤部分运算符是左结合（从左到右执⾏），少数运算符是右
//结合（从右到左执⾏）

/********10.表达式求值********/
//*****整型提升
//1. 有符号整数提升是按照变量的数据类型的符号位来提升的
//2. ⽆符号整数提升，⾼位补0

//int -- signed int
//char 是signed char 还是unsigned char取决于编译器
//在常见的编译器上char = signed char

//int main()
//{
//	/*int a = 10;
//	short s = 5;
//	int b = a + s;*/
//
//	char c1 = 5;
//	char c2 = 126;
//	char c3 = c1 + c2;//131
//	//00000000 00000000 00000000 00000101
//	//00000101 - c1
//	//00000000 00000000 00000000 01111110
//	//01111110 - c2
//	//
//	//00000000 00000000 00000000 00000101 - c1 --发生整型提升
//	//00000000 00000000 00000000 01111110 - c2 --发生整型提升
//
//	//00000000 00000000 00000000 10000011
//	//10000011 - c3
//	//%d 是打印10进制有符号的整数
//	//11111111 11111111 11111111 10000011 - c3 - 发生整型提升 补码
//	//10000000 00000000 00000000 01111100 - 反码
//	//10000000 00000000 00000000 01111101 - 原码
//	//-125
//
//	printf("%d\n",c3);//-125
//	return 0;
//}


//******算术转换
//如果某个操作符的各个操作数属于不同的类型，那么除⾮其中⼀个操作数的转换为另⼀个操作数的类
//型，否则操作就⽆法进⾏。下⾯的层次体系称为寻常算术转换

//字节往长的转换

//问题表达式解析

//int main()
//{
//	//1.
//	int a, b, c, d, e, f;
//	a* b + c * d + e * f;
//
//	//2.
//	c + --c;
//	
//	return 0;
//}

//3.
//int main()
//{
//	int i = 10;
//	i = i-- - --i * (i = -3) * i++ + ++i;
//	printf("i = %d\n", i);
//	return 0;
//}

//4.
//int fun()
//{
//	static int count = 1;
//	return ++count;
//}
//int main()
//{
//	int answer;
//	answer = fun() - fun() * fun();
//	printf("%d\n", answer);//输出多少？
//	return 0;
//}

//5.
//int main()
//{
//	int i = 1;
//	int ret = (++i) + (++i) + (++i);
//	printf("%d\n", ret);
//	printf("%d\n", i);
//	return 0;
//}